/*****************************************************
 * 本文件函数用于记录标定参数，断电不丢失
 *****************************************************/

#include "InnerFlash.h"
#include <xc.h>
//dsPIC33EP256GP50X, dsPIC33EP256MC20X/50X, PIC24EP256GP/MC20X这类256K的器件
//用户编程flash存储有88K个指令字空间，地址范围为:0x000200-0x02AFEA
//写锁存器占2个指令字，地址为：0xFA0000和0xFA0002
//USERID起始为0x800FF8，结束0x800FFE
//DEVID起始0xFF0000，结束0xFF0002


//定义存储数据所在空间的起始地址,0x02A000，结束地址为0x2AFE8，可存储数据量为:(0x2AFE8-0x2A000+2)/2=4074
#define DATA_RECORD_START_PAGE 0x0002
#define DATA_RECORD_START_ADDR 0xA000


//index要小于4074,目前开辟的最大的用于存储数量的空间索引为4073
//读取flash内容
uint16_t DataRecord_ReadData(uint16_t index)
{
    return InnerFlash_ReadFlashLow(DATA_RECORD_START_PAGE, DATA_RECORD_START_ADDR+index*2);
}


//index要小于4074,目前开辟的最大的用于存储数量的空间索引为4073
//往flash写入内容
uint16_t DataRecord_WriteData(uint16_t index, uint16_t data)
{
    uint16_t pageStartAddr;
    
    if(index>4073)
        return 0xa5a5;
    
    //读取对应地址数据，若数据与要写入的一致，则不再写入
    uint16_t dataTmp = InnerFlash_ReadFlashLow(DATA_RECORD_START_PAGE, DATA_RECORD_START_ADDR+index*2);
    if(dataTmp==data)
        return 0xffff;
    
    //取对应页的首地址
    pageStartAddr = DATA_RECORD_START_ADDR+index*2;
    
    
    //先读取一页，再擦除，修改读取数据，写入一页
    uint16_t pageData[1024],count,i;
    count = pageStartAddr/0x800;
    pageStartAddr = 0x800*count;
    //先将对应页的数据全部读出来，0x800个地址，0x400个字
    for(i=0;i<0x800;i+=2)
    {
        pageData[i/2] = InnerFlash_ReadFlashLow(DATA_RECORD_START_PAGE,pageStartAddr+i);
    }
    
    //擦除整页
    InnerFlash_EraseFlashPage(DATA_RECORD_START_PAGE,pageStartAddr);
    
    //修改数据，每1024个数据pageData索引要从0重新开始
    pageData[index-(index/1024)*1024] = data;
    
    //将修改后的数据写回该页
    InnerFlash_WriteFlashNoHigh(DATA_RECORD_START_PAGE,pageStartAddr,pageData,1024);

    return 0;
}

//不允许数组超过一页
uint16_t DataRecord_WriteDataArray(uint16_t index, uint16_t *data, uint16_t length)
{
    uint16_t pageStartAddr,i,dataTmp,cmpNZ=0;
    uint16_t pageData[1024],count;
    
    //超过一页
    if(((index%1024)+length)>1023)
        return 0xa5a5;
    
    
    for(i=0;i<length;i++)
    {
        //读取对应地址数据，若数据与要写入的一致，则不再写入
        dataTmp = InnerFlash_ReadFlashLow(DATA_RECORD_START_PAGE, DATA_RECORD_START_ADDR+(index+i)*2);
        if(dataTmp!=data[i]) //只要有一个数据不同，则需要重新写入
        {
            cmpNZ = 1;
            break;
        }
    }
    
    if(cmpNZ==0) //数据完全一致，不写入
        return 0xffff;
    
    
    
    //取对应页的首地址
    pageStartAddr = DATA_RECORD_START_ADDR+index*2;
    
    
    //先读取一页，再擦除，修改读取数据，写入一页
    
    count = pageStartAddr/0x800;
    pageStartAddr = 0x800*count;
    //先将对应页的数据全部读出来，0x800个地址，0x400个字
    for(i=0;i<0x800;i+=2)
    {
        pageData[i/2] = InnerFlash_ReadFlashLow(DATA_RECORD_START_PAGE,pageStartAddr+i);
    }
    
    //擦除整页
    InnerFlash_EraseFlashPage(DATA_RECORD_START_PAGE,pageStartAddr);
    
    for(i=0;i<length;i++)
    {
        //修改数据，每1024个数据pageData索引要从0重新开始
        pageData[index-(index/1024)*1024+i] = data[i];
    }
    
    //将修改后的数据写回该页
    InnerFlash_WriteFlashNoHigh(DATA_RECORD_START_PAGE,pageStartAddr,pageData,1024);

    return 0;
}